/*
 * arch/ckcore/gx3xxx/irq.c ---IRQ vector handles
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2006 Hangzhou NationalChip co.,ltd.
 * Copyright (C) 2011 by lubin <lubin@nationalchip.com>
 */
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <mach/ckpic.h>


static unsigned int irq_num[NR_IRQS];
static unsigned char *base_va;


/*
 *  Mask the interrupt and the irp number is irqno.
 */
static void
gx3xxx_irq_mask(unsigned int irqno)
{
	unsigned int mask;

	if (irqno<32)
		{
			mask = __raw_readl(GX3XXX_INTC_NMASK_L(base_va));
			mask |= 1<<(irqno);
			__raw_writel(mask,GX3XXX_INTC_NMASK_L(base_va));
		}else{
		mask = __raw_readl(GX3XXX_INTC_NMASK_H(base_va));
			mask |= 1<<(irqno-32);
			__raw_writel(mask,GX3XXX_INTC_NMASK_H(base_va));}		
	
}


/*
 *  Unmask the interrupt and the irp number is irqno.
 */
static void
gx3xxx_irq_unmask(unsigned int irqno)
{

	unsigned int mask;

	if (irqno<32)
		{
			mask = __raw_readl(GX3XXX_INTC_NMASK31_00(base_va));
			mask &= ~(1<<(irqno));
			__raw_writel(mask,GX3XXX_INTC_NMASK31_00(base_va));
		}else{
		mask = __raw_readl(GX3XXX_INTC_NMASK63_32)(base_va));
		mask &= ~(1<<(irqno-32));
			__raw_writel(mask,GX3XXX_INTC_NMASK63_32(base_va));}	
	

}

static inline void
gx3xxx_irq_ack(unsigned int irqno)
{
	return 0;
}

static inline void
gx3xxx_irq_maskack(unsigned int irqno)
{
	return 0;
}



struct irq_chip gx3xxx_irq_chip = {
        .name           = "gx3xxx",
        .ack            = gx3xxx_irq_ack,
        .mask           = gx3xxx_irq_mask,
        .unmask         = gx3xxx_irq_unmask,
        .set_wake       = gx3xxx_irq_wake
};


static struct map_desc gx3201_intc_desc[] __initdata ={
	{
		.virtual = GX3201_VA_INTC,
		.pfn = __phys_to_pfn(GX3201_PA_INTC),
		.length = 0x1000,
		.type = MT_DEVICE,
	}
    
};



/*
 *  Initial the interrupt controller of c-sky.
 */
void __init gx3xxx_init_IRQ(void)
{
	
	unsigned int i;

	
	iotable_init(gx3201_intc_desc,ARRAY_SIZE(gx3201_intc_desc));

	base_va = (unsigned char*)gx3201_intc_desc[0].virtual;


	for (i = 0; i < NR_IRQS; ++i)
		{
			set_irq_handler(i,handle_level_irq);
			set_irq_chip(&gx3xxx_irq_chip);
			set_irq_flags(i,IRQF_VALID);	

			if(i%4 == 0)
				__raw_writel(0xFFFFFFFF,GX3201_VA_INTC_SOURCE + i);
		}
	
	memset(&irq_num,0xFF,NR_IRQS);

	/* enable all interrupt */
	__raw_writel(0xFFFFFFFF,GX3201_VA_INTC_NEN31_00);
	__raw_writel(0xFFFFFFFF,GX3201_VA_INTC_NEN63_32);

	/* mask all interrupt */
	__raw_writel(0xFFFFFFFF,GX3201_VA_INTC_NMASK31_00);
	__raw_writel(0xFFFFFFFF,GX3201_VA_INTC_NMASK63_32);

}

